<template>
  <div v-show="visible" class="cg-dialog-wrapper">
    <div ref="dialogRef" class="cg-dialog" :style="style">
      <div class="cg-dialog-header">
        <slot name="title">
          <span class="cg-dialog-title">{{ title }}</span>
        </slot>
        <button type="button" class="cg-dialog-headerbtn" v-if="showClose" @click="handleClose">
          <svg-icon icon-name="close" />
        </button>
      </div>
      <div class="cg-dialog-body">
        <slot></slot>
      </div>
      <div class="cg-dialog-footer" v-if="$slots.footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import PopupMixin from '../tools/popup/index'

// 定义组件名称
defineOptions({
  name: 'cg-dialog'
})

// 定义props
const props = withDefaults(
  defineProps<{
    title: string
    width?: string
    showClose: boolean
    visible: boolean
    beforeClose?: (action: () => void) => void
  }>(),
  {
    title: '标题',
    showClose: true
  }
)

// 定义emits
const emit = defineEmits(['update:visible', 'close'])

// 响应式变量
const top = ref('15vh')
const transparent = ref(false)
const timeout = ref<NodeJS.Timeout | undefined>(undefined)
const closed = ref(false)
const dialogRef = ref<HTMLElement | null>(null)

// 获取组件实例
const instance = getCurrentInstance()

// 手动实现Popup mixin功能
const open = () => {
  // Popup mixin中的open方法是空实现，这里保持同样的行为
}

const close = () => {
  // Popup mixin中的close方法是空实现，这里保持同样的行为
}

// 监听visible变化 (复制自Popup mixin)
watch(
  () => props.visible,
  (val) => {
    if (val) {
      open()
      updateTop()
    } else {
      close()
    }
  }
)

// 计算属性
const style = computed(() => {
  const style: Record<string, string | number> = {
    opacity: transparent.value ? 0 : 1,
    marginTop: top.value
  }
  if (props.width) {
    style.width = props.width
  }
  return style
})

// 生命周期钩子
onMounted(() => {
  if (props.visible) {
    open()
    updateTop()
  }
})

onUnmounted(() => {
  if (timeout.value) {
    clearTimeout(timeout.value)
  }
})

// 方法
function updateTop() {
  transparent.value = true
  if (timeout.value) {
    clearTimeout(timeout.value)
  }
  timeout.value = setTimeout(() => {
    try {
      const dialog = dialogRef.value
      if (dialog) {
        const dRect = dialog.getBoundingClientRect()
        // 使用document.body代替this.$el
        const rect = document.body.getBoundingClientRect()
        if (rect instanceof DOMRect) {
          top.value = (rect.height - dRect.height) / 2 + 'px'
        }
      }
    } catch (error) {
      console.log(error)
    }
    transparent.value = false
  }, 40)
}

function handleClose() {
  if (typeof props.beforeClose === 'function') {
    props.beforeClose(hide)
  } else {
    hide()
  }
}

function hide(cancel = false) {
  if (cancel !== false) {
    emit('update:visible', false)
    emit('close')
    closed.value = true
  }
}

// 暴露方法
defineExpose({
  hide
})
</script>

<style lang="scss">
@use './style.scss';
</style>
